require 'logger'
require 'proxy_pump/const'
module ProxyPump
  class Configuration

    def initialize(pairs = {})
      @entities = {}
      pairs[:pump]          ||= Const::DEFAULT_PUMP_CONF
      pairs[:server]        ||= Const::DEFAULT_SERVER_CONF
      pairs[:redis]         ||= Const::DEFAULT_REDIS_CONF
      pairs[:database]      ||= Const::DEFAULT_DATABASE_CONF
      pairs[:proxy_timeout] ||= Const::DEFAULT_PROXY_TIMEOUT
      pairs[:log_level]     ||= Const::DEFAULT_LOG_LEVEL
      merge! pairs
    end

    def [](key)
      convert_key(key) { |ck| @entities[ck] }
    end

    def []=(key, val)
      assign(key, val)
    end

    def fetch(key, default = nil, &block)
      convert_key(key) { |ck| @entities.fetch(ck, default, &block) }
    end

    def update(attrs)
      tap { attrs.each { |k,v| assign(k,v) } }
    end
    alias_method :merge!, :update

    def merge(attrs)
      dup.merge!(attrs)
    end

    def inspect
      @entities.each_with_object("#<#{self.class}") { |(k,v), output| output << " :#{k}=#{v.inspect}" } << ">"
    end

    def to_s
      inspect
    end

    def to_h
      @entities
    end

    def each_pair(&block)
      @entities.each_pair(&block)
    end

    def each(&block)
      @entities.each(&block)
    end

    def delete(key)
      convert_key(key) { |ck| @entities.delete(ck) }
    end

    def to_ary
      nil
    end

    def logger=(new_logger)
      @logger = if new_logger.respond_to?(:call)
                  new_logger.call
                else
                  new_logger
                end
      @logger.tap { |logger| logger.level = log_level }
    end

    def logger
      @logger ||= ::Logger.new(STDOUT).tap { |logger| logger.level = log_level }
    end

    private

      def method_missing(method_name, *args, &block)
        if method_name[-1] == '='
          self[method_name[0..-2]] = args.first
        elsif @entities.has_key?(method_name)
          self[method_name]
        else
          super
        end
      end

      def convert_key(key)
        ck = key.to_s.underscore.to_sym
        if block_given?
          yield ck
        else
          ck
        end
      end

      def assign(key, val)
        convert_key(key) { |ck| @entities[ck] = val }
      end

  end # Configuration
end # ProxyPump
